package com.xbongbong.paas.script.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.paas.elasticsearch.constant.EsMappingConstant;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.dto.PaasFormDataEsMappingDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsInitVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author: yingjf
 * @date: 2022/10/31 09:31
 * @description:
 */
@Slf4j
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/workOrderV2/es")
public class WorkOrderInitScriptController {
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;

    /**
     * 初始化tb_work_order_v2_node_log_info 表的es
     * date: 2022/10/31 09:34
     * @author yingjf
     * @param paasFormDataEsMappingDTO:
     * @param br:
     */
    @RequestMapping(value = "/nodeInfo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String formStaticsData(@RequestBody @Valid PaasFormDataEsMappingDTO paasFormDataEsMappingDTO, BindingResult br) throws Exception {
        XbbResponse<PaasFormDataEsInitVO> response;

        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if(!proBaseConfig.getXbbCode().equals(paasFormDataEsMappingDTO.getXbbCode())){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                PaasFormDataEsInitVO paasFormDataEsInitVO = initWorkOrderNodeLogInfoEs(paasFormDataEsMappingDTO);
                response = new XbbResponse<>(paasFormDataEsInitVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 删除mapping
     * date: 2022/10/31 09:41
     * @author yingjf
     * @param paasFormDataEsMappingDTO:
     * @param br:
     */
    @RequestMapping(value = "/delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String delete(@RequestBody @Valid PaasFormDataEsMappingDTO paasFormDataEsMappingDTO, BindingResult br) throws Exception {
        XbbResponse<BaseVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if(!proBaseConfig.getXbbCode().equals(paasFormDataEsMappingDTO.getXbbCode())){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                BaseVO baseVO = deleteMapping(paasFormDataEsMappingDTO);
                response = new XbbResponse<>(baseVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 添加别名
     * @param paasFormDataEsMappingDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/addAlias", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String addAlias(@RequestBody @Valid PaasFormDataEsMappingDTO paasFormDataEsMappingDTO, BindingResult br) throws Exception {
        XbbResponse<PaasFormDataEsInitVO> response;

        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if(!proBaseConfig.getXbbCode().equals(paasFormDataEsMappingDTO.getXbbCode())){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                PaasFormDataEsInitVO paasFormDataEsInitVO = addAlias(paasFormDataEsMappingDTO);
                response = new XbbResponse<>(paasFormDataEsInitVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }



    public PaasFormDataEsInitVO initWorkOrderNodeLogInfoEs(PaasFormDataEsMappingDTO paasFormDataEsMappingDTO) throws XbbException {
        PaasFormDataEsInitVO paasFormDataEsInitVO = new PaasFormDataEsInitVO();
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_WORK_ORDER_V2_NODE_INFO;
        try {
            String indexName  = indexTypeEnum.getRealName();
            String type = indexTypeEnum.getType();
            JSONObject rootSetting = (JSONObject) JSONObject.parse(EsMappingConstant.ELASTIC_SETTINGS_ROOT);
            //----------------------上面是创建index  ，下面是mapping
            String noSubRelate = "{\"type\":\"join\",\"relations\":{\"" + indexTypeEnum.getType()+ "\":[]}}";
            JSONObject mappingJson = (JSONObject) JSONObject.parse(EsMappingConstant.ELASTIC_MAPPING_ROOT);
            JSONObject properties = mappingJson.getJSONObject("properties");
            mappingJson.put("dynamic","strict");
            //外层
            JSONObject outJsonObject = new JSONObject();
            outJsonObject.put("dataId", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("corpid", JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("appId", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("formId", JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("menuId", JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("workOrderId", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("nodeId", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("nodeType", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("transferTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("transferReason", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("transferUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("isTransfer", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("isLastTransfer", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("refuseTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("refuseReason", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("refuseUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("isLastRefuse", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("cancelTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("cancelReason", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("cancelUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("isLastCancel", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("visitTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("visitUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("isLastVisit", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("startTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("finishTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("stayTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("isFinish", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("acceptStartTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("acceptStartUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("acceptFinishTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("acceptFinishUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
//            outJsonObject.put("acceptInTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
//            outJsonObject.put("acceptOutTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("acceptStayTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("startStartTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("startStartUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("startStayTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
//            outJsonObject.put("stayInTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
//            outJsonObject.put("stayOutTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("startSignTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("startSignUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("startFinishTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("startFinishUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("finishStartTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("finishStartUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("finishSignBackTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("finishSignBackUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("finishFinishTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("finishFinishUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
//            outJsonObject.put("finishInTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
//            outJsonObject.put("finishOutTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("finishStayTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("assignedTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("assignedUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("freeFinishUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("settlementUser", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_TEXT));
            outJsonObject.put("flowStatus", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("versionId", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put("addTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("updateTime", (JSONObject) JSONObject.parse(EsMappingConstant.MAPPING_FOR_DATE_SECOND));
            outJsonObject.put("del", JSONObject.parse(EsMappingConstant.MAPPING_FOR_LONG));
            outJsonObject.put(ElasticConstant.MY_JOIN_FIELD, JSONObject.parse(noSubRelate));
            //仅存储
            outJsonObject.put("esId", JSONObject.parse(EsMappingConstant.MAPPING_FOR_NOT_ANALYZED));
            JSONObject json = new JSONObject();
            json.put(type, mappingJson);
            properties.putAll(outJsonObject);
            JSONObject rootJson = new JSONObject();
            rootJson.put("mappings", mappingJson);
            rootJson.put("settings", rootSetting);
            log.info("settingAndMapping============="+ JSON.toJSONString(rootJson, SerializerFeature.DisableCircularReferenceDetect));
            CreateIndexRequest request = new CreateIndexRequest(indexName);
            request.source(rootJson);
            CreateIndexResponse createIndexResponse = xbbElasticsearchRestTemplate.getRestHighLevelClient(indexName).indices().create(request, RequestOptions.DEFAULT);
            boolean acknowledged = createIndexResponse.isAcknowledged();
            if(acknowledged !=true){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            log.info("=============建立{}索引成功=============",indexTypeEnum.getIndex());
        } catch (Exception e) {
            log.error("=============建立{}索引失败=============",indexTypeEnum.getIndex());
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return paasFormDataEsInitVO;
    }


    public BaseVO deleteMapping(PaasFormDataEsMappingDTO paasFormDataEsMappingDTO) throws XbbException {
        // 这里只让删除工单相关的索引
        List<IndexTypeEnum> workOrderIndexList = Arrays.asList(IndexTypeEnum.IDX_WORK_ORDER_V2_NODE_INFO);

        List<Integer> businessTypeList = paasFormDataEsMappingDTO.getBusinessTypeList();
        for (IndexTypeEnum indexTypeEnum : workOrderIndexList) {
            if (businessTypeList.contains(indexTypeEnum.getCode())) {
                String esIndex = indexTypeEnum.getRealName();
                //删除索引
                try {
                    xbbElasticsearchRestTemplate.deleteIndex(esIndex);
                    log.error("删除索引===============================================" + indexTypeEnum.getCode());
                } catch (XbbException e) {
                    log.error(SystemErrorCodeEnum.API_ERROR_100001.getMsg(), e);
                }
            }
        }
        log.error("delete mapping===============================================over");
        return new BaseVO();
    }


    public PaasFormDataEsInitVO addAlias(PaasFormDataEsMappingDTO paasFormDataEsMappingDTO) throws XbbException {
        PaasFormDataEsInitVO dataInitVO = new PaasFormDataEsInitVO();
        HttpEntity httpEntity = null;
        try {
            IndexTypeEnum indexTypeEnum = EsHelper.getIndexTypeEnum(paasFormDataEsMappingDTO);
            if (Objects.equals(1, paasFormDataEsMappingDTO.getSpecial())) {
                indexTypeEnum = IndexTypeEnum.IDX_SAAS_CUSTOMER_SPECIAL;
            }
            String alias = indexTypeEnum.getIndex();
            String index = indexTypeEnum.getRealName();
            Request request = new Request("GET","/" + index + "/_alias/");
            Response response = xbbElasticsearchRestTemplate.getRestClient(index).performRequest(request);
            JSONObject entityJson = (JSONObject) JSONObject.parse(EntityUtils.toString(response.getEntity()));
            JSONObject result = entityJson.getJSONObject(index).getJSONObject("aliases");
            String msg = "";
            if(result!=null && !result.isEmpty()){
                Set<String> key = result.keySet();
                msg = key.toString();

            }
            Request addRequest = new Request("POST","/_aliases");
            httpEntity = new NStringEntity("{\"actions\":[{\"add\":{\"index\":\"" + index +
                    "\",\"alias\":\"" + alias +
                    "\"}}]}", ContentType.APPLICATION_JSON);
            addRequest.setEntity(httpEntity);
            xbbElasticsearchRestTemplate.getRestClient(index).performRequest(addRequest);
            dataInitVO.setMsg(msg + alias);
        } catch (Exception e) {
            log.error("",e);
            throw  new XbbException(BiErrorCodeEnum.API_ERROR_241011);
        } finally {
            if (Objects.nonNull(httpEntity)) {
                try {
                    ((NStringEntity) httpEntity).close();
                } catch (Exception e) {
                    log.error("",e);
                }
            }
        }
        return dataInitVO;
    }

}
